﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using RayDen.Library.Core;
using RayDen.RayEngine.Core.Devices;
using RayDen.RayEngine.Core.Types;
using RayDen.RayEngine.Data;

namespace RayDen.RayEngine.IntersectionEngines {
    using RayInfo = RayData;
    using BVHAccel =
    //BoundingVolumeHierarchyAccelerationStructure;
    BvhAccelHelper;

    public class CpuBvhIntersectionEngine : IntersectionEngine {
        private readonly ConcurrentQueue<RayBuffer> todoRayBuffers, doneRayBuffers;
        protected BVHAccel accel;

        public CpuBvhIntersectionEngine(RayEngineScene scene) : base(scene) {
            doneRayBuffers = new ConcurrentQueue<RayBuffer>();
            todoRayBuffers = new ConcurrentQueue<RayBuffer>();
            accel = new BvhAccelHelper(scene);
            /*
            accel = new BoundingVolumeHierarchyAccelerationStructure();
            accel.Init(scene, scene.MaterialProvider);
             * */
        }

        public override void PushRayBuffer(RayBuffer rayBuffer, int clientIdx) {
            todoRayBuffers.Enqueue(rayBuffer);
            Trace(rayBuffer);
            doneRayBuffers.Enqueue(rayBuffer);
        }

        public override RayBuffer PopRayBuffer(int info) {
            RayBuffer result;
            doneRayBuffers.TryDequeue(out result);
            return result;
        }


        public override void Trace(RayBuffer rayBuffer) {
            var rb = rayBuffer.RaysInfo;
            var hb = rayBuffer.rayHits;
            var rayCount = rayBuffer.RaysInfo.Length;
            for (int i = 0; i < rayCount; ++i)
                this.Intersect(ref rb[i], ref  hb[i]);

            statsTotalRayCount += rayCount;
            rayBuffer.traced = true;
            doneRayBuffers.Enqueue(rayBuffer);
        }

        private void Intersect(ref RayInfo rayInfo, ref  RayHit rayHit) {
            //accel.Intersect(ref rayInfo, out rayHit);
        }


        public override void Start() {
            this.started = true;
        }

        public override void Stop() {
            started = false;
            RayBuffer rb;
            while (doneRayBuffers.Any())
                doneRayBuffers.TryDequeue(out rb);
        }
    }
}
